/* Copyright (c) 2008 Erik Beeson
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * Redistributions of source code must retain the
 *     above copyright notice, this list of conditions
 *     and the following disclaimer.
 * Redistributions in binary form must reproduce the
 *     above copyright notice, this list of conditions
 *     and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 * Neither the name of Erik Beeson nor YourSharade nor the
 *     names of its contributors may be used to endorse or
 *     promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.restly.representations;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import org.restly.*;
import org.restly.servlet.RestlyHttpServletRequest;
import org.restly.servlet.RestlyContext;
import org.restly.servlet.RestlyHttpServletResponse;
import org.restly.core.ContentType;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * Oct 25, 2008, 8:38:53 AM
 *
 * @author <a href="http://restly.org/">Erik Beeson</a>
 */
public class SerializedRepresentation implements Representation {
	private static final XStream xstream = new XStream();

	static {
		xstream.autodetectAnnotations(true);
	}

	private final Object o;
	private final String stylesheet;
	private final HttpStatus status;

	public SerializedRepresentation(Object o) {
		this(o, "");
	}

	public SerializedRepresentation(Object o, HttpStatus status) {
		this(o, "", status);
	}

	public SerializedRepresentation(Object o, String stylesheet) {
		this(o, stylesheet, HttpStatus.OK);
	}
	public SerializedRepresentation(Object o, String stylesheet, HttpStatus status) {
		this.o = o;
		this.stylesheet = stylesheet;
		this.status = status;
	}

	public void represent(RestlyContext context, RestlyHttpServletRequest request, RestlyHttpServletResponse response) throws IOException {
		ContentType contentType = request.getPreferredContentType();

		response.setStatus(status);

		if(ContentType.JSON.equals(contentType)) {
			response.setContentType(ContentType.JSON);
			xstream.marshal(o, new JsonHierarchicalStreamWriter(response.getWriter()));
		} else {
			response.setContentType(ContentType.TEXT_XML);
			PrintWriter writer = response.getWriter();
			writer.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");

			String stylesheetUrl = context.getStylesheetLocator().getStylesheetUrl(request, status, stylesheet);

			if(stylesheetUrl != null) {
				writer.println("<?xml-stylesheet type=\"text/xsl\" href=\"" + stylesheetUrl + "\"?>");
			}

			xstream.marshal(o, new PrettyPrintWriter(writer));
		}
	}

	public String toString() {
		return new StringBuffer()
				.append(this.getClass().getName()).append("[")
				.append(o)
				.append("]")
				.toString();
	}

	public boolean equals(Object object) {
		if(object != null && object instanceof SerializedRepresentation) {
			SerializedRepresentation that = (SerializedRepresentation) object;
			return ((this.o == null) ? (that.o == null) : this.o.equals(that.o)) &&
					((this.stylesheet == null) ? (that.stylesheet == null) : this.stylesheet.equals(that.stylesheet));
		}
		return false;
	}

}
